package socketmvc.server.ws;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.intf.TioUuid;
import org.tio.server.TioServer;
import org.tio.server.TioServerConfig;
import org.tio.utils.Threads;
import org.tio.utils.thread.pool.SynThreadPoolExecutor;
import org.tio.websocket.common.WsTioUuid;
import org.tio.websocket.server.WsServerConfig;
import org.tio.websocket.server.WsTioServerListener;
import org.tio.websocket.server.handler.IWsMsgHandler;
import socketmvc.server.tcp.TcpServer;
import socketmvc.server.tcp.TcpServerConfig;

import java.io.IOException;
import java.util.concurrent.ThreadPoolExecutor;

public class WsServer {

    private static final Logger log = LoggerFactory.getLogger(WsServer.class);
    private final WsServerConfig wsServerConfig;
    private final IWsMsgHandler wsMsgHandler;
    private final WsServerHandler wsServerHandler;
    private final WsTioServerListener wsTioServerListener;
    private final TioServerConfig tioServerConfig;
    private final TioServer tioServer;

    public TioServer getTioServer() {
        return this.tioServer;
    }

    public WsServerConfig getWsServerConfig() {
        return this.wsServerConfig;
    }

    public IWsMsgHandler getWsMsgHandler() {
        return this.wsMsgHandler;
    }

    public WsServerHandler getWsTioServerHandler() {
        return this.wsServerHandler;
    }

    public WsTioServerListener getWsTioServerListener() {
        return this.wsTioServerListener;
    }

    public TioServerConfig getTioServerConfig() {
        return this.tioServerConfig;
    }

    public WsServer(int port, IWsMsgHandler wsMsgHandler) throws IOException {
        this(port, wsMsgHandler, (SynThreadPoolExecutor)null, (ThreadPoolExecutor)null);
    }

    public WsServer(int port, IWsMsgHandler wsMsgHandler, SynThreadPoolExecutor tioExecutor, ThreadPoolExecutor groupExecutor) throws IOException {
        this(new WsServerConfig(port), wsMsgHandler, tioExecutor, groupExecutor);
    }

    public WsServer(WsServerConfig wsServerConfig, IWsMsgHandler wsMsgHandler) throws IOException {
        this(wsServerConfig, wsMsgHandler, (SynThreadPoolExecutor)null, (ThreadPoolExecutor)null);
    }

    public WsServer(WsServerConfig wsServerConfig, IWsMsgHandler wsMsgHandler, SynThreadPoolExecutor tioExecutor, ThreadPoolExecutor groupExecutor) throws IOException {
        this(wsServerConfig, wsMsgHandler, new WsTioUuid(), tioExecutor, groupExecutor);
    }

    public WsServer(WsServerConfig wsServerConfig, IWsMsgHandler wsMsgHandler, TioUuid tioUuid, SynThreadPoolExecutor tioExecutor, ThreadPoolExecutor groupExecutor) throws IOException {
        if (tioExecutor == null) {
            tioExecutor = Threads.getTioExecutor();
        }

        if (groupExecutor == null) {
            groupExecutor = Threads.getGroupExecutor();
        }

        this.wsServerConfig = wsServerConfig;
        this.wsMsgHandler = wsMsgHandler;
        this.wsServerHandler = new WsServerHandler(wsServerConfig, wsMsgHandler);
        this.wsTioServerListener = new WsServerListener();
        this.tioServerConfig = new TcpServerConfig("SocketMvc Websocket Server", this.wsServerHandler, this.wsTioServerListener, tioExecutor, groupExecutor);
        this.tioServerConfig.setHeartbeatTimeout(0L);
        this.tioServerConfig.setTioUuid(tioUuid);
        this.tioServerConfig.setReadBufferSize(132476);
        this.tioServer = new TcpServer(this.tioServerConfig);
    }

    public void start() throws IOException {
        this.tioServer.start(this.wsServerConfig.getBindIp(), this.wsServerConfig.getBindPort());
    }
}
